package vn.nt.healthcare.server.ws.service.impl;

import java.util.Date;
import java.util.List;

import vn.nt.healthcare.server.ws.util.Constants;
import vn.nt.healthcare.server.ws.util.DateUtil;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import vn.nt.healthcare.server.ws.domain.Company;
import vn.nt.healthcare.server.ws.model.Customer;
import vn.nt.healthcare.server.ws.model.Doctor;
import vn.nt.healthcare.server.ws.model.Schedule;
import vn.nt.healthcare.server.ws.model.Subjects;
import vn.nt.healthcare.server.ws.repositories.CompanyRepository;
import vn.nt.healthcare.server.ws.service.ScheduleService;

@Service("scheduleService")
@Transactional
public class ScheduleServiceImpl implements ScheduleService {

	@Autowired
	private CompanyRepository companyRepository;

	@SuppressWarnings("unchecked")
	@Override
	public List<Schedule> findSchedulesByStaffInDate(String companyId,
			String status, int staffId) {
		Company company = companyRepository.findByCode(companyId);
		if (company == null) {
			return null;
		} else {
			Session session = null;
			try {
				session = ServiceHelper.openSession(company);
				StringBuilder sql = new StringBuilder(
						"SELECT DISTINCT s FROM Schedule s WHERE LOWER(s.stateOrder) = LOWER(:status) AND s.doctor.Id = :staffId");
				sql.append(" AND s.startTime >= :beginTime AND s.startTime <= :endTime");
				sql.append(" ORDER BY s.startTime ");
				Query query = session.createQuery(sql.toString());
				query.setString("status", status);
				query.setInteger("staffId", staffId);
				query.setTimestamp("beginTime",
						DateUtil.getStartOfDay(new Date()));
				query.setTimestamp("endTime", DateUtil.getEndOfDay(new Date()));
				return query.list();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				ServiceHelper.closeSession(session);
			}
		}
		return null;
	}

	@Override
	public Schedule findScheduleById(String companyId, int id) {
		Company company = companyRepository.findByCode(companyId);
		if (company != null) {
			Session session = null;
			try {
				session = ServiceHelper.openSession(company);
				Schedule se = (Schedule) session.get(Schedule.class, id);
				return se;
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				ServiceHelper.closeSession(session);
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Schedule> findSchedulesInTime(String companyId, String status,
			int staffId, boolean isMorning) {
		// TODO Auto-generated method stub
		Company company = companyRepository.findByCode(companyId);
		if (company != null) {
			Session session = null;
			try {
				session = ServiceHelper.openSession(company);
				StringBuilder sql = new StringBuilder(
						"SELECT DISTINCT s FROM Schedule s WHERE LOWER(s.stateOrder) = LOWER(:status) AND s.doctor.Id = :staffId");
				sql.append(" AND s.startTime >= :beginTime AND s.startTime <= :endTime");
				sql.append(" ORDER BY s.startTime ");
				Query query = session.createQuery(sql.toString());
				query.setInteger("staffId", staffId);
				query.setString("status", status);
				if (isMorning) {
					query.setTimestamp("beginTime",
							DateUtil.getStartOfDay(new Date()));
					query.setTimestamp("endTime",
							DateUtil.getEndOfMorning(new Date()));
				} else {
					query.setTimestamp("beginTime",
							DateUtil.getStartOfAfternoon(new Date()));
					query.setTimestamp("endTime",
							DateUtil.getEndOfDay(new Date()));
				}
				return query.list();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				ServiceHelper.closeSession(session);
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Schedule> findSchedulesByCustomer(String companyId,
			String status, int customerId, int staffId) {
		// TODO Auto-generated method stub
		Company company = companyRepository.findByCode(companyId);
		if (company != null) {
			Session session = null;
			try {
				session = ServiceHelper.openSession(company);
				StringBuilder sql = new StringBuilder(
						"SELECT DISTINCT s FROM Schedule s WHERE s.customer.Id = :customerId");
				if (staffId > -1) {
					sql.append(" AND s.doctor.Id = :staffId");
				}
				sql.append(" ORDER BY s.startTime desc");
				Query query = session.createQuery(sql.toString());
				query.setInteger("customerId", customerId);
				if (staffId > -1) {
					query.setInteger("staffId", staffId);
				}
				return query.list();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				ServiceHelper.closeSession(session);
			}
		}
		return null;
	}

	@Override
	public Schedule order(String companyId, int staffId, Date orderTime,
			String content, int customId, int subjectId) {
		// TODO Auto-generated method stub
		Company company = companyRepository.findByCode(companyId);
		if (company != null) {
			Session session = null;
			Transaction transaction = null;
			try {
				session = ServiceHelper.openSession(company);
				transaction = session.beginTransaction();
				Doctor doctor = (Doctor) session.get(Doctor.class, staffId);
				Customer customer = (Customer) session.get(Customer.class,
						customId);
				Subjects sub = (Subjects) session
						.get(Subjects.class, subjectId);
				Schedule schedule = new Schedule();
				schedule.setStartTime(orderTime);
				schedule.setDoctor(doctor);
				schedule.setStateOrder(Constants.STATUS_REQUEST);
				schedule.setCoinBonus(0);
				schedule.setDesc(content);
				schedule.setCustomer(customer);
				schedule.setSubject(sub);
				session.saveOrUpdate(schedule);
				transaction.commit();
				return schedule;
			} catch (Exception e) {
				if (transaction != null) {
					transaction.rollback();
				}
				e.printStackTrace();
			} finally {
				ServiceHelper.closeSession(session);
			}
		}
		return null;
	}

	@Override
	public Schedule updateSchedule(String companyId, int id, String status,
			Date orderTime) {
		Company company = companyRepository.findByCode(companyId);
		if (company != null) {
			Session session = null;
			Transaction transaction = null;
			try {
				session = ServiceHelper.openSession(company);
				transaction = session.beginTransaction();
				Schedule schedule = (Schedule) session.get(Schedule.class, id);
				schedule.setStartTime(orderTime);
				schedule.setStateOrder(status);
				session.saveOrUpdate(schedule);
				transaction.commit();
				return schedule;
			} catch (Exception e) {
				// TODO: handle exception
				if (transaction != null)
					transaction.rollback();
				e.printStackTrace();
			} finally {
				ServiceHelper.closeSession(session);
			}
		}
		return null;
	}

	@Override
	public boolean destroySchedule(String companyId, int id) {
		Company company = companyRepository.findByCode(companyId);
		if (company != null) {
			Session session = null;
			Transaction transaction = null;
			try {
				session = ServiceHelper.openSession(company);
				transaction = session.beginTransaction();
				Schedule schedule = (Schedule) session.get(Schedule.class, id);
				session.delete(schedule);
				transaction.commit();
				return true;
			} catch (Exception e) {
				if (transaction != null)
					transaction.rollback();
				e.printStackTrace();
			} finally {
				ServiceHelper.closeSession(session);
			}
		}
		return false;
	}

}
